home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Utilities / Scion / ARexx / PrintDescendant.rexx < prev    next >
OS/2 REXX Batch file  |  1997-11-04  |  24KB  |  820 lines

  1. /****************************************************************************
  2.  *                                                                          *
  3.  * $VER: PrintDescendant 2.06 (25 Nov 1996)
  4.  *                                                                          *
  5.  *                      Written by Freddy Ariës                             *
  6.  * Address: Lindeboomweg 7, NL-7135 KE Harreveld, The Netherlands.          *
  7.  *                                                                          *
  8.  * Output options:                                                          *
  9.  *  1. Descendant Chart - all descendants [Dutch: parenteel]                *
  10.  *  2. Descendant Chart - male descendants (mention daughters, no children) *
  11.  *     [Dutch: genealogie - nageslacht van zonen, maar vermelding dochters] *
  12.  *  3. Descendant Chart - male descendants (leave out daughters)            *
  13.  *     [Dutch: stamboom - nageslacht van zonen, geen vermelding dochters]   *
  14.  *                                                                          *
  15.  * This script uses (by default) the rexxreqtools.library (which requires   *
  16.  * a version of reqtools larger than 2.0 and rexxsyslib.library)            *
  17.  * If you do not have these, run SetDefaults.rexx to change the settings.   *
  18.  *                                                                          *
  19.  * As of v2 of this script, and Scion V4, the current person on Scion's     *
  20.  * Personal Window will be used to determine where the search starts.       *
  21.  * Scion 3.13 can still be used, though, in which case the user will be     *
  22.  * asked at which IRN he wants to start.                                    *
  23.  *                                                                          *
  24.  * So why this PrintDescendant script when Scion already has a print option *
  25.  * for descendant charts? Well, the reason is simple: the format of the     *
  26.  * descendant charts generated by Scion does not conform to the guidelines  *
  27.  * of the Dutch CBG (Central Bureau for Genealogy) and NGV (Nederlandse     *
  28.  * Genealogische Vereniging; Dutch Genealogical Society). So I created my   *
  29.  * own PrintDescendant script, that *does* follow their guidelines.         *
  30.  *                                                                          *
  31.  * DONE:                                                                    *
  32.  *  - Now uses preference file for default settings                         *
  33.  *  - count the number of lines output and give a linefeed after a certain  *
  34.  *    number (ie. skip page breaks)                                         *
  35.  *  - Inclusion of name/address data from prefs (optional)                  *
  36.  *                                                                          *
  37.  * TO DO (mostly low priority, unless someone really wants this):           *
  38.  *  - allow user to select output format (Dutch CGB, New England Register   *
  39.  *    system (NEHGR) or New England Record system (NGS), a modified Henry   *
  40.  *    System, etc.                                                          *
  41.  *  - find a good way to handle the people with sex '?'                     *
  42.  *  - add a menu option for the maximum number of generations to print      *
  43.  *  - allow user to specify if he wants burial data, occupation, comments,  *
  44.  *    references fields, etc. printed.                                      *
  45.  *  - option: if the person has multiple marriages, output a list to the    *
  46.  *    screen and let the user select one (1..x), or all (0).                *
  47.  *  - include Scion v5 submitter data                                       *
  48.  *  - Suggestions, comments, bugreports, donations, etc. are appreciated.   *
  49.  *                                                                          *
  50.  ****************************************************************************/
  51.  
  52. options failat 20; options results
  53. arg prtin outname noirn mgen outval
  54.  
  55. versionstr = "2.05"
  56.  
  57. /* Don't change the settings here! Run SetDefaults.rexx instead! */
  58. usereq = 1; outp = 1; useirn = 1
  59. prtdev = stdout; prtopt = 0; scrdev = stdout
  60. plwidth = 78; pgsize = 0
  61. subf = 0; subm. = ""
  62. PSCR = 'SCIONGEN'
  63.  
  64. scrname = "CON:0//639//Scion_Output/AUTO/WAIT/CLOSE/SCREEN"
  65. pgline = 1
  66. NL = '0A'x
  67.  
  68. signal on IOERR
  69.  
  70. do while prtin = '?'
  71.   Tell("NUMOPT/A/N,OUTFILE/A,NOIRN/S,MAXGEN/N,NOREQ/S,QUIET/S: ")
  72.   pull prtin outname noirn mgen outval
  73. end
  74.  
  75. /* read preferences file */
  76.  
  77. if open(pfile, 'ENV:Scion/ScionRexx.prefs', 'r') then do
  78.   do while ~eof(pfile)
  79.     inln = readln(pfile)
  80.     if inln ~= "" then do
  81.       wstr = upper(word(inln, 1))
  82.  
  83.       select
  84.     when wstr = "USEREQ" then
  85.       usereq = 1
  86.     when wstr = "NOUSEREQ" then
  87.       usereq = 0
  88.     when wstr = "PUBSCREEN" then
  89.       pscr = strip(delstr(inln, 1, length(wstr)), 'b', ' "')
  90.     when wstr = "LINEWIDTH" then
  91.       do
  92.         wstr = word(inln, 2)
  93.             if datatype(wstr, 'w') then plwidth = wstr
  94.       end
  95.     when wstr = "PAGESIZE" then
  96.       do
  97.             wstr = word(inln, 2)
  98.             if datatype(wstr, 'w') then pgsize = wstr
  99.       end
  100.     when wstr = "SUB_N0" then
  101.       subm.0 = delstr(inln, 1, length(wstr)+1)
  102.     when wstr = "SUB_A1" then
  103.       subm.1 = delstr(inln, 1, length(wstr)+1)
  104.     when wstr = "SUB_A2" then
  105.       subm.2 = delstr(inln, 1, length(wstr)+1)
  106.     when wstr = "SUB_A3" then
  107.       subm.3 = delstr(inln, 1, length(wstr)+1)
  108.     when wstr = "SUB_T0" then
  109.       subm.4 = delstr(inln, 1, length(wstr)+1)
  110.     when wstr = "SUB_N1" then
  111.       subm.5 = delstr(inln, 1, length(wstr)+1)
  112.     when wstr = "SUB_N2" then
  113.       subm.6 = delstr(inln, 1, length(wstr)+1)
  114.     when wstr = "SUB_N3" then
  115.       subm.7 = delstr(inln, 1, length(wstr)+1)
  116.     when wstr = "SUB_F0" then
  117.       subf = bittst(b2c(strip(delstr(inln, 1, length(wstr)), 'b')), 1)
  118.     otherwise
  119.       /* unrecognized? skip */
  120.       end
  121.     end
  122.   end
  123.   close(pfile)
  124. end
  125.  
  126. if pscr = "" | (pscr ~= "WORKBENCH" & ~show('p', pscr)) then
  127.   pscr = "SCIONGEN"
  128. scrname = scrname||pscr
  129.  
  130. /* Command line options get priority over global settings */
  131.  
  132. ParseArguments()
  133.  
  134. if ~show('l','rexxarplib.library') then do
  135.     call addlib('rexxarplib.library',0,-30,0)
  136. end
  137.  
  138. screentofront(pscr)
  139.  
  140. if usereq & ~show('l','rexxreqtools.library') then do
  141.   if exists('libs:rexxreqtools.library') then
  142.     call addlib('rexxreqtools.library',0,-30,0)
  143.   else do
  144.     usereq = 0; outp = 1
  145.     Tell("Unable to open rexxreqtools.library - using text output")
  146.   end
  147. end
  148.  
  149. /* Originally stolen from Peter Billing - thanks Peter ;-) */
  150. if ~show('P','SCIONGEN') then do
  151.   EndString('I am sorry to say that the SCION Genealogist' || NL ||,
  152.     'database is not available. Please start the' || NL ||,
  153.     'SCION program BEFORE using this script!')
  154. end
  155.  
  156. /* TO DO: localize:
  157.   if ~show('l','locale.library') then do
  158.     call addlib('locale.library',0,-30,0)
  159.   end
  160.   catalog = OpenCatalog("scion.catalog","english",0)
  161.   "DESCENDANT CHART - ALL DESCENDANTS"
  162.   "DESCENDANT CHART - ONLY MALE DESCENDANTS (TYPE I)"
  163.   "DESCENDANT CHART - ONLY MALE DESCENDANTS (TYPE II)"
  164.   date()
  165.  */
  166.  
  167. myport = "SCIONGEN"
  168. address value myport
  169. GETDBNAME
  170. dbname = upper(RESULT)
  171. fill = 7;        /* number of spaces at the beginning of lines */
  172. malesex = 'M';   /* as of V4, sexes are always 'M', 'F' or '?' */
  173. femalesex = 'F'
  174. GETPROGVERSION
  175. progvers = RESULT
  176.  
  177. if progvers >= 4 then do
  178.   GETCURRENTIRN
  179.   irn = RESULT
  180. end
  181.  
  182. if outp & ~usereq then do
  183.   if pscr ~= "WORKBENCH" then do
  184.     scrdev = 'SCNDSCSCR'
  185.     if ~open(scrdev, scrname, 'w') then scrdev = stdout
  186.   end
  187.   Tell("*** PrintDescendant version "||versionstr||" ***")
  188.   Tell("***        by Freddy Ariës       ***")
  189.   Tell("Current database: "||dbname||NL)
  190. end
  191. if prtopt = 0 then do
  192.   if usereq then do
  193.     prtopt = rtezrequest('Current Scion database: '||dbname||NL||,
  194.       NL||'Please make your choice: '||,
  195.       NL||' 1. Descendant Chart - all descendants'||,
  196.       NL||' 2. Descendant Chart - male descendants'||,
  197.       NL||'    (mention daughters, without children)'||,
  198.       NL||' 3. Descendant Chart - male descendants'||,
  199.       NL||'    (leave out daughters)'||,
  200.       '',' _1 | _2 | _3 |E_xit','PrintDescendant v'||versionstr||' by Freddy Ariës','rt_pubscrname = '||PSCR)
  201.     if prtopt = 0 then EXIT
  202.  
  203.     if progvers < 4 then do
  204.       irn = rtgetlong(,'Enter the IRN of the person whose'||,
  205.             NL||'descendants you want to print: '||,
  206.             NL,'Input Request:','_Continue','rt_pubscrname = '||PSCR)
  207.       if irn = '' then EndString("No IRN - aborted.")
  208.       irn = abs(irn)
  209.     end
  210.  
  211.     useirn = rtezrequest('Do you want to output the IRNs'||,
  212.               NL||'(the record numbers) as well?'||,
  213.               '',' _Yes| _No ','Input Request:','rt_pubscrname = '||PSCR)
  214.   end
  215.   else do
  216.     /* No use in asking for input if we're not allowed to output anything */
  217.     Tell("1. Descendant Chart - all descendants")
  218.     Tell("2. Descendant Chart - male descendants (mention daughters, without children)")
  219.     Tell("3. Descendant Chart - male descendants (leave out daughters)")
  220.     TellNN("Your choice: ")
  221.     prtopt = readln(scrdev)
  222.     prtopt = CheckAnswer(upper(word(prtopt, 1)))
  223.  
  224.     if progvers < 4 then do
  225.       TellNN("Enter the IRN of the person whose descendants you want to print: ")
  226.       irn = readln(scrdev)
  227.       irn = upper(word(irn, 1))
  228.     end
  229.  
  230.     TellNN("Do you want to output the IRNs (numbers) as well (y/n)? ")
  231.     instr = readln(scrdev)
  232.     instr = upper(left(instr, 1))
  233.     Tell("")
  234.     if instr = "Y" then useirn = 1
  235.     else useirn = 0
  236.   end
  237. end
  238.  
  239. if progvers < 4 then do
  240.   irn = CheckIRN(irn)
  241. end
  242.  
  243. EXISTPERSON irn
  244. if RESULT ~= 'YES' then
  245. do
  246.   if progvers >= 4 then
  247.     EndString("Unable to locate current person in the current database.")
  248.   else
  249.     EndString("No person with IRN "||irn||" in the current database.")
  250. end
  251.  
  252. if prtopt > 1 then do
  253.   GETSEX irn
  254.   parsex = RESULT
  255.   if prtopt = 3 & parsex = femalesex then
  256.     EndString("Person isn't male - nothing to print.")
  257. end
  258.  
  259. if outp then do
  260.   /* No use trying to get input if we're not allowed to ask anything */
  261.   pname = GetNameStr(irn, 0)
  262.   if prtopt = 1 | parsex = malesex then do
  263.     if usereq then do
  264.       valcont = rtezrequest('The selected person is: '||NL||pname||'.'||,
  265.         NL||'Continue?','_Continue| _Abort','PrintDescendant Request:','rt_pubscrname = '||PSCR)
  266.       if valcont = 0 then EndString("Aborted.")
  267.     end
  268.     else do
  269.       TellNN("Current person is "||pname||". Continue? (y/n) ")
  270.       valcont = readln(scrdev)
  271.       valcont = upper(left(valcont, 1))
  272.       if valcont ~= 'Y' then EndString("Ok.")
  273.     end
  274.   end
  275.   else do
  276.     /* with prtopt = 2, we would only print the (generation I) female and
  277.      * her husbands, but no children!
  278.      */
  279.     if usereq then do
  280.       valcont = rtezrequest("WARNING!!! Person "||NL||pname||,
  281.         NL||"is not male! Continue anyway?",'_Continue| _Abort','PrintDescendant Request:','rt_pubscrname = '||PSCR)
  282.       if valcont = 0 then EndString("Aborted.")
  283.     end
  284.     else do
  285.       Tell("WARNING! Person "||pname||" isn't male!")
  286.       TellNN("Continue anyway? (y/n) ")
  287.       valcont = readln(scrdev)
  288.       valcont = upper(left(valcont, 1))
  289.       if valcont ~= 'Y' then EndString("Ok.")
  290.     end
  291.   end
  292. end
  293.  
  294. /* TO DO: (at this location:)
  295.  * If the person has multiple marriages, output the spouse name, IRN
  296.  * and FGRN to screen, and let the user select one (1..x), or all (0)
  297.  */
  298.  
  299. if outp & outname = "" then do
  300.   if usereq then do
  301.     odev = rtezrequest('Current Scion database: '||dbname||,
  302.       NL||'Where should the output be sent to?'||,
  303.       NL,' _File |_Printer|_Screen|_Nowhere','PrintDescendant v'||versionstr||' by Freddy Ariës','rt_pubscrname = '||PSCR)
  304.     select
  305.       when odev = 1 then do
  306.         /* We need a file requester for further data */
  307.         dblen = length(dbname)
  308.         if dblen>6 & right(dbname, 6)=".SCION" then
  309.           dbname=left(dbname, dblen - 6)
  310.         outname = rtfilerequest(,dbname||'.DSC','Output filename',,'rtfi_buffer = true   rt_pubscrname = '||PSCR||'   rtfi_initialpath = RAM:',)
  311.         if outname = '' then
  312.           outname = dbname||'.DSC'
  313.       end
  314.       when odev = 2 then
  315.         outname = 'PRT:'
  316.       when odev = 3 then
  317.         outname = 'STDOUT'
  318.       otherwise EndString("No output - aborted.")
  319.         /* You selected 'Nowhere' */
  320.     end
  321.   end
  322.   else do
  323.     Tell("Enter output file (filename with complete path, or PRT: for printer,")
  324.     TellNN("or STDOUT for screen): ")
  325.     outname = readln(scrdev)
  326.     outname = strip(outname, 'b', ' "')
  327.     if outname = "" then outname = 'STDOUT'
  328.   end
  329. end
  330.  
  331. /* Anyone know a better way to translate numbers into Roman? */
  332. GenerationS.1 = "I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII XIX XX"
  333. GenerationS.2 = "XXI XXII XXIII XXIV XXV XXVI XXVII XXVIII XXIX XXX XXXI XXXII XXXIII XXXIV XXXV XXXVI XXXVII XXXVIII IXL XL"
  334. MaxChild = 26
  335.  
  336. /* Printer Codes, some of which are currently unused: */
  337. ESC = '1B'x
  338. prtinit = ESC||"#1";     /* ESC#1 initialize      */
  339. prtundon = ESC||"[4m";   /* ESC[4m underline on   */
  340. prtundoff = ESC||"[24m"; /* ESC[24m underline off */
  341. prtdson = ESC||"[1m";    /* ESC[1m boldface on    */
  342. prtdsoff = ESC||"[22m";  /* ESC[22m boldface off  */
  343. prtnlqon = ESC||"[2"||'22'x||"z"; /* ESC[2"z NLQ on */
  344. prtnlqoff = ESC||"[1"||'22'x||"z"; /* ESC[1"z NLQ off */
  345.  
  346. if ~usereq then
  347.   Tell("Printing...")
  348.  
  349. OpenPrinter()
  350.  
  351. childnums = irn; childgens = "1"
  352. alcount = 0; chcount = 0
  353.  
  354. do while childnums ~= ""
  355.   irn = word(childnums, 1)
  356.   cgen = word(childgens, 1)
  357.   if cgen ~= currgen then do
  358.     alcount = 0
  359.     /* New generation: reset alfabet counter */
  360.     currgen = cgen
  361.     genchild = 0
  362.   end
  363.   childnums = delstr(childnums, 1, length(irn)+1)
  364.   childgens = delstr(childgens, 1, length(currgen)+1)
  365.  
  366.   ccnt = 1
  367.   /* Sex to use with options 2 and 3 */
  368.   GETSEX irn
  369.   parsex = RESULT
  370.  
  371.   g1 = GetPersonStr(irn)
  372.   mnum = 0
  373.   GETMARRIAGE irn mnum
  374.   fgrn = RESULT
  375.   EXISTFAMILY fgrn
  376.   ftrue = RESULT
  377.  
  378.   do while ftrue = 'YES'
  379.     m1 = GetMarriageStr(fgrn)
  380.     ptn = GetPartnerIRN(fgrn, irn)
  381.     if ptn ~= 0 then do
  382.       if m1 ~= "" then m1 = m1||' '
  383.       m1 = m1||GetPersonStr(ptn)
  384.     end
  385.     if m1 ~= "" then m1 = ", m: "||m1
  386.     if ccnt = 1 then do
  387.       ggs = GetGenStr(currgen, 0)
  388.       if currgen > 1 then do
  389.         alcount = alcount + 1
  390.     /* TO DO: only if this person has any siblings who have children,
  391.      *      or if there are other persons (with children) on this
  392.      *      generation
  393.      */
  394.         ggs = ggs||D2C(alcount+96)
  395.       end
  396.       ggs = left(ggs||".       ", fill)
  397.       m1 = ggs||g1||m1||'.'
  398.       ccnt = 0
  399.     end
  400.     else
  401.       m1 = copies(' ',fill)||g1||m1||'.'
  402.     PrintLines(m1, fill)
  403.     if prtopt ~= 3 | parsex = malesex then
  404.       chcount = chcount + PrintChildren(fgrn, parsex)
  405.     PrintLF()
  406.     mnum = mnum + 1
  407.     GETMARRIAGE irn mnum
  408.     fgrn = RESULT
  409.     EXISTFAMILY fgrn
  410.     ftrue = RESULT
  411.   end
  412.   if mnum = 0 then do
  413.     m1 = GetGenStr(currgen,fill)||g1
  414.     PrintLines(m1, fill)
  415.     if currgen = 1 then
  416.       PrintLines("No marriages are recorded for this person.", 0)
  417.     PrintLF()
  418.   end
  419. end
  420. if currgen = 1 & chcount = 0 then do
  421.   if prtopt = 1 then
  422.     PrintLines("No descendants are recorded for person.")
  423.   else 
  424.     PrintLines("No male descendants are recorded for person.")
  425. end
  426.  
  427. writech(prtdev, prtnlqoff)
  428. EndString("Done.")
  429.  
  430. EXIT
  431.  
  432. /* Parse command line arguments */
  433. ParseArguments:
  434. if noirn = "NOIRN" then useirn = 0
  435. else if noirn = "QUIET" || noirn = "NOREQ" then do
  436.   outval = noirn
  437.   noirn = ""
  438. end
  439. else do
  440.   outval = mgen
  441.   mgen = noirn
  442.   noirn = ""
  443. end
  444. if mgen = "QUIET" || mgen = "NOREQ" then do
  445.   outval = mgen
  446.   mgen = ""
  447. end
  448.  
  449. MaxGens = 40; /* due to the Roman numbers, we can't handle more */
  450. if mgen ~= "" then do
  451.   if DATATYPE(mgen, 'w') & mgen > 0 & mgen < MaxGens then
  452.     MaxGens = mgen
  453. end
  454.  
  455. if outval = "QUIET" then do
  456.   usereq = 0
  457.   outp = 0
  458. end
  459. else if outval = "NOREQ" then
  460.   usereq = 0
  461.  
  462. if prtin = "" then do
  463.   prtopt = 0
  464.   if ~outp then EndString("Requires argument is missing.")
  465.     /* actually, with outp = 0, all it does is EXIT */
  466. end
  467. else do
  468.   prtopt = CheckAnswer(prtin)
  469.   /* Note that it was important to establish outp before calling these */
  470. end  
  471. return 0
  472.  
  473. OpenPrinter:
  474. /* Open the printer device and print out a nice header */
  475. if outname = 'STDOUT' then do
  476.   if ~outp | usereq then do /* output screen wasn't opened yet! */
  477.     scrdev = 'SCNDSCSCR'
  478.     if ~open(scrdev, scrname, 'w') then scrdev = stdout
  479.   end
  480.   prtdev = scrdev
  481. end
  482. else do
  483.   prtdev = 'PRINTER'
  484.   if ~open(prtdev, outname, 'w') then
  485.     EndString("ERROR: Failed to open output file!")
  486. end
  487. writech(prtdev, prtinit||prtnlqon)
  488. if prtopt = 1 then
  489.   prtstr = "DESCENDANT CHART - ALL DESCENDANTS"
  490. else if prtopt = 2 then
  491.   prtstr = "DESCENDANT CHART - ONLY MALE DESCENDANTS (TYPE I)"
  492. else
  493.   prtstr = "DESCENDANT CHART - ONLY MALE DESCENDANTS (TYPE II)"
  494. prtstr = prtundon||prtdson||prtstr||prtdsoff||prtundoff
  495. DoWrite(prtdev, prtstr)
  496. if subf then do
  497.   if subm.0 ~= "" then DoWrite(prtdev, subm.0)
  498.   if subm.1 ~= "" then DoWrite(prtdev, subm.1)
  499.   if subm.2 ~= "" then DoWrite(prtdev, subm.2)
  500.   if subm.3 ~= "" then DoWrite(prtdev, subm.3)
  501.   if subm.4 ~= "" then DoWrite(prtdev, subm.4)
  502.   if subm.5 ~= "" then DoWrite(prtdev, subm.5)
  503.   if subm.6 ~= "" then DoWrite(prtdev, subm.6)
  504.   if subm.7 ~= "" then DoWrite(prtdev, subm.7)
  505. end
  506. prtstr = prtdson||"Report printed on: "||date()||prtdsoff
  507.  
  508. DoWrite(prtdev, prtstr)
  509. prtstr = copies('=', plwidth)
  510. DoWrite(prtdev, prtstr)
  511. return 0
  512.  
  513. PrintLines: PROCEDURE EXPOSE prtdev plwidth prtopt pgline pgsize
  514. parse arg ostr, fill
  515. /* TO DO:
  516.  * if there are control strings within ostr (like prtdson or prtdsoff)
  517.  * don't include them in the length count
  518.  */
  519. do while ostr ~= ""
  520.   nnl = plwidth+1
  521.   if length(ostr) > plwidth then do
  522.     do until pc = ' ' | nnl = 1
  523.       pc = substr(ostr, nnl, 1)
  524.       nnl = nnl - 1
  525.     end
  526.     if nnl = 1 then do
  527.       prtstr = left(ostr, plwidth)
  528.       ostr = delstr(ostr, 1, nnl)
  529.     end
  530.     else do
  531.       prtstr = left(ostr, nnl)
  532.       ostr = delstr(ostr, 1, nnl+1)
  533.     end
  534.   end
  535.   else do
  536.     prtstr = ostr
  537.     ostr = ""
  538.   end
  539.   DoWrite(prtdev, prtstr)
  540.   if ostr ~= "" then
  541.     ostr = copies(' ',fill)||ostr
  542. end
  543. return 0
  544.  
  545. PrintLF:
  546. DoWrite(prtdev, "")
  547. return 1
  548.  
  549. /*
  550.  * output at most #pgsize lines per page to the print device
  551.  * if pgsize = 0, this feature is turned off (unlimited #lines per page)
  552.  */
  553. DoWrite: PROCEDURE EXPOSE pgline pgsize
  554. parse arg prtdev, ostr
  555. if pgsize ~= 0 & pgline > pgsize then do
  556.   writech(prtdev, '0C'x); /* CTRL-L; next page */
  557.   pgline = 0
  558. end
  559. writeln(prtdev, ostr)
  560. pgline = pgline + 1
  561. return 0
  562.  
  563. PrintChildren:
  564. parse arg ffnum, parsx
  565. /* If we turn this into a PROCEDURE, we'll have to EXPOSE quite a bit!
  566.  * The disadvantage now is that we have to be extremely careful
  567.  * not to overwrite any global variables by accident!
  568.  */
  569. cidx = 0; cham = 0
  570. GETCHILD ffnum cidx
  571. chld = RESULT
  572. EXISTPERSON chld
  573. ctrue = RESULT
  574. nextgen = currgen + 1
  575. if nextgen > MaxGens then return cham
  576.   /* Maximum number of generations reached! */
  577. do while ctrue = 'YES'
  578.   cidx = cidx + 1
  579.   if prtopt > 1 then do
  580.     GETSEX chld
  581.     csx = RESULT
  582.   end
  583.   if prtopt ~= 3 | csx = malesex then do
  584.     cham = cham + 1
  585.     m1 = copies(' ',8)||cham||". "||GetChildStr(chld)
  586.     if (prtopt = 1 | csx = malesex) & HasChild(chld) then do
  587.       childnums = childnums||chld||' '
  588.       childgens = childgens||nextgen||' '
  589.       genchild = genchild + 1
  590.       if genchild > MaxChild then return 1
  591.       /* Maximum number of children reached! */
  592.       /* TO DO: if genchild = 1 and the current person has no siblings,
  593.        *    or none of his siblings have any children of their own,
  594.        *    and if there are no other persons with children on this
  595.        *    generation, then leave off the D2C part
  596.        */
  597.       m1 = m1||", see "||GetGenStr(nextgen, 0)||D2C(genchild+96)
  598.     end
  599.     else
  600.       m1 = m1||GetDeathStr(chld)||GetMarriages(chld)
  601.     PrintLines(m1||'.', 11)
  602.   end
  603.   GETCHILD ffnum cidx
  604.   chld = RESULT
  605.   EXISTPERSON chld
  606.   ctrue = RESULT
  607. end
  608. return cham
  609.  
  610. GetGenStr: PROCEDURE EXPOSE GenerationS.
  611. parse arg gnum, fill
  612. if gnum <= 20 then
  613.   gstr = word(GenerationS.1, gnum)
  614. else if gnum <= 40 then
  615.   gstr = word(GenerationS.2, gnum)
  616. else
  617.   return ""
  618. if fill > 0 then
  619.   gstr = left(gstr||".       ",fill)
  620. return gstr
  621.  
  622. GetPersonStr: PROCEDURE EXPOSE useirn
  623. parse arg irn
  624. if irn ~= 0 then do
  625.   nstr = GetNameStr(irn)
  626.   nstr = nstr||GetBirthStr(irn)
  627.   nstr = nstr||GetDeathStr(irn)
  628. end
  629. else
  630.   nstr = "UNKNOWN"
  631. return nstr
  632.  
  633. GetChildStr: PROCEDURE EXPOSE useirn
  634. parse arg irn
  635. if irn ~= 0 then do
  636.   nstr = GetNameStr(irn)
  637.   nstr = nstr||GetBirthStr(irn)
  638. end
  639. else
  640.   nstr = "UNKNOWN"
  641. return nstr
  642.  
  643. /* check all marriages for children; only accept male children for option 3 */
  644. HasChild: PROCEDURE EXPOSE prtopt malesex
  645. parse arg irn
  646. mnum = 0
  647. GETMARRIAGE irn mnum
  648. marr = RESULT
  649. EXISTFAMILY marr
  650. mtrue = RESULT
  651. do while mtrue = 'YES'
  652.   chnxt = 0
  653.   GETCHILD marr chnxt
  654.   ch = RESULT
  655.   EXISTPERSON ch
  656.   ct = RESULT
  657.   if prtopt < 3 then do
  658.     if ct = 'YES' then return 1
  659.   end
  660.   else do
  661.     /* For option 3: search for male children */
  662.     do while ct = 'YES'
  663.       GETSEX ch
  664.       csx = RESULT
  665.       if csx = malesex then return 1
  666.       chnxt = chnxt + 1
  667.       GETCHILD marr chnxt
  668.       ch = RESULT
  669.       EXISTPERSON ch
  670.       ct = RESULT
  671.     end
  672.   end
  673.   mnum = mnum + 1
  674.   GETMARRIAGE irn mnum
  675.   marr = RESULT
  676.   EXISTFAMILY marr
  677.   mtrue = RESULT
  678. end
  679. return 0
  680.  
  681. GetNameStr: PROCEDURE EXPOSE useirn
  682. parse arg gnum
  683. GETFIRSTNAME gnum
  684. name = RESULT
  685. if name ~= "" then name = name||" "
  686. GETLASTNAME gnum
  687. lname = RESULT
  688. if lname = "" then lname = "UNKNOWN"
  689. name = name||lname
  690. if useirn then name = name||" ["gnum"]"
  691. return name
  692.  
  693. GetBirthStr: PROCEDURE
  694. parse arg gnum
  695. GETBIRTHPLACE gnum
  696. bstr = RESULT
  697. GETBIRTHDATE gnum
  698. bdat = RESULT
  699. if bdat ~= "" & bstr ~= "" then bstr = bstr||" "
  700. bstr = bstr||bdat
  701. if bstr ~= "" then bstr = ", b: "||bstr
  702. return bstr
  703.  
  704. GetDeathStr: PROCEDURE
  705. parse arg gnum
  706. GETDEATHPLACE gnum
  707. dstr = RESULT
  708. GETDEATHDATE gnum
  709. ddat = RESULT
  710. if ddat ~= "" & dstr ~= "" then dstr = dstr||" "
  711. dstr = dstr||ddat
  712. if dstr ~= "" then dstr = ", d: "||dstr
  713. return dstr
  714.  
  715. GetMarriages: PROCEDURE EXPOSE useirn
  716. parse arg irn
  717. mstr = ""
  718. GETMARRIAGE irn 0
  719. mf = RESULT
  720. EXISTFAMILY mf
  721. if RESULT = 'YES' then do
  722.   mtrue = 1
  723.   GETMARRIAGE irn 1
  724.   m2 = RESULT
  725.   EXISTFAMILY m2
  726.   if RESULT = 'YES' then mset = 1
  727.   else mset = 0
  728. end
  729. else
  730.   mtrue = 0  
  731. mnum = 0
  732. do while mtrue
  733.   m1 = GetMarriageStr(mf)
  734.   if m1 ~= "" then m1  = m1||' '
  735.   ptn = GetPartnerIRN(mf, irn)
  736.   m1 = m1||GetPersonStr(ptn)
  737.  
  738.   if mset then mstr = ", m("||mnum||"): "||m1
  739.   else mstr = ", m: "||m1
  740.  
  741.   mnum = mnum + 1    
  742.   GETMARRIAGE irn mnum
  743.   mf = RESULT
  744.   EXISTFAMILY mf
  745.   if RESULT ~= 'YES' then mtrue = 0
  746. end
  747. return mstr
  748.  
  749. GetMarriageStr: PROCEDURE
  750. parse arg mf
  751. GETMARRYPLACE mf
  752. mstr = RESULT
  753. GETMARRYDATE mf
  754. mdat = RESULT
  755. if mdat ~= "" & mstr ~= "" then mstr = mstr||" "
  756. mstr = mstr||mdat
  757. return mstr
  758.  
  759. GetPartnerIRN: PROCEDURE
  760. parse arg fnum, inum
  761. GETPRINCIPAL fnum
  762. prn = RESULT
  763. GETSPOUSE fnum
  764. sps = RESULT
  765. if inum = prn then pnum = sps
  766. else if inum = sps then pnum = prn
  767. else pnum = 0
  768. EXISTPERSON pnum
  769. if RESULT ~= 'YES' then pnum = 0
  770. return pnum
  771.  
  772. CheckAnswer: PROCEDURE EXPOSE outp prtdev usereq scrdev pscr
  773. parse arg str
  774. str = left(str, 1)
  775. if ~DATATYPE(str, 'w') | (str < 1 | str > 3) then
  776.   EndString("Invalid option - aborted.")
  777. return str
  778.  
  779. CheckIRN: PROCEDURE EXPOSE outp prtdev usereq scrdev pscr
  780. parse arg str
  781. if ~DATATYPE(str, 'w') then
  782.   EndString("Invalid IRN - aborted.")
  783. return str
  784.  
  785. Tell: PROCEDURE EXPOSE outp scrdev
  786. parse arg str
  787. if outp then
  788.   writeln(scrdev, str)
  789. return 0
  790.  
  791. TellNN: PROCEDURE EXPOSE outp scrdev
  792. parse arg str
  793. if outp then
  794.   writech(scrdev, str)
  795. return 0
  796.  
  797. EndString: PROCEDURE EXPOSE outp prtdev usereq scrdev pscr
  798. parse arg str
  799. /* If you turned off stdout, no error messages will be shown! */
  800. if usereq then
  801.   rtezrequest(str,'E_xit','PrintDescendant Message:','rt_pubscrname = '||PSCR)
  802. else do
  803.   Tell(str || '0A'x)
  804. end
  805. if outp & ~usereq & (scrdev ~= stdout) then do
  806.   Tell("Press <return> to exit.")
  807.   readln(scrdev)
  808.   close(scrdev)
  809. end
  810. close(prtdev)
  811. EXIT
  812.  
  813. /* Let's make sure you get a nice message when you turn off the printer :-) */
  814.  
  815. IOERR:
  816. bline = SIGL
  817. say "I/O error #"||RC||" detected in line "||bline||":"
  818. say sourceline(bline)
  819. EXIT
  820.